
import 'dart:convert';
import 'dart:ffi';
import 'dart:math';
import 'dart:typed_data';

import 'package:jl_plugin/bean/EqInfo.dart';
import 'package:jl_plugin/bean/JlResult.dart';
import 'package:jl_plugin/callback/BtRcspCallBack.dart';

import 'bean/ADVInfoResponse.dart';
import 'bean/BlueDevice.dart';
import 'bean/HistoryBluetoothDevice.dart';
import 'bean/KeySettings.dart';
import 'callback/OpusDecodeCallBack.dart';
import 'jl_plugin_platform_interface.dart';
typedef OnPhoneCallStatusChange = void Function(int status);
typedef BlueDeviceCallback = void Function(BlueDevice device);
typedef JlOnErrorCallBack = void Function(JlResult jlResule);
typedef JlOnDevicesSuccessCallBack = void Function(ADVInfoResponse advInfo);
typedef JlEqChangeCallBack = void Function(EqInfo info);
typedef JlDeviceCommandCallBack = void Function(int type,String receiveCmd,Uint8List bytes);
typedef JlDeviceCommandDecodeCallBack = void Function(int type,String receiveCmd,Uint8List bytes);
class JlPlugin {
  static JlPlugin _instance =  JlPlugin._internal();
  JlPlugin._internal() {
    _initMethodCallHandler();
  }
  final List<BlueDeviceCallback> _scanListeners = [];
  final List<BtRcspCallBack> _btListeners = [];
  final List<JlEqChangeCallBack> _eqSettingChange = [];
  final List<JlDeviceCommandCallBack> commandCmdCallBack = [];
  OpusDecodeCallBack? opusDecodeCallBack;
  JlDeviceCommandDecodeCallBack? jlDeviceCommandDecodeCallBack;
  OnPhoneCallStatusChange? phoneCallStatusChange;

  /// The default instance of [JlPluginPlatform] to use.
  ///
  /// Defaults to [MethodChannelJlPlugin].
  static JlPlugin get instance => _instance;

  void _initMethodCallHandler() {
    JlPluginPlatform.instance.methodChannel.setMethodCallHandler((call) async {
      print("_initMethodCallHandler->${call.method}");
      switch(call.method){
        case 'blueDevice':
          final device = BlueDevice.fromMap(Map.from(call.arguments));
          for (var listener in _scanListeners) {
            listener(device);
          }
          break;
        case 'onConnection':
          final device = BlueDevice.fromMap(call.arguments);
          for (var cb in _btListeners) {
            cb.onConnected(device);
          }
          break;
        case 'onBondStatus':
          final device = BlueDevice.fromMap(call.arguments);
          for (var cb in _btListeners) {
            cb.onBondStatus(device);
          }
          break;
        case 'onDeviceCommand':
          for (var cb in commandCmdCallBack) {
            var cmdMap=Map.from(call.arguments);
            int type=cmdMap["cmd"]["type"];
            String receiveCmd=cmdMap["cmd"]["receiveCmd"];
            Uint8List bytes=cmdMap["cmd"]["byte"];
            cb(type,receiveCmd,bytes);
          }
          break;
        case 'onDeviceCommandDecode':
          if(jlDeviceCommandDecodeCallBack!=null){
            var cmdMap=Map.from(call.arguments);
            int type=cmdMap["cmd"]["type"];
            String receiveCmd=cmdMap["cmd"]["receiveCmd"];
            Uint8List bytes=cmdMap["cmd"]["byte"];
            jlDeviceCommandDecodeCallBack!(type,receiveCmd,bytes);
          }
          break;
        case 'onEqChange':
          print("onEqChange2222------------${call.arguments}");
          var eqInfo = EqInfo.fromJson(Map.from(call.arguments));
          print("onEqChange1111------------${eqInfo.toString()}");
          for (var eq in _eqSettingChange) {
            eq(eqInfo);
          }
          break;
        case "onDecodeStart":
          if(opusDecodeCallBack!=null){
            opusDecodeCallBack!.onDecodeStart();
          }
          break;
        case "onDecodeStream":
          if(opusDecodeCallBack!=null){
            var map=Map.from(call.arguments);
            var dataByte=map["data"] as Uint8List;
            opusDecodeCallBack!.onDecodeStream(dataByte);
          }
          break;
        case "onDecodeComplete":
          if(opusDecodeCallBack!=null){
            opusDecodeCallBack!.onDecodeComplete();
          }
          break;
        case "onDecodeError":
          if(opusDecodeCallBack!=null){
            var map=Map.from(call.arguments);
            var code=map["code"] as int;
            var message=map["message"] as String;
            opusDecodeCallBack!.onDecodeError(code, message);
          }
          break;
        case "onPhoneCallStatusChange":
          if(phoneCallStatusChange!=null){
            var map=Map.from(call.arguments);
            var status=map["status"] as int;
            phoneCallStatusChange!(status);
          }

          break;
      }
    });
  }

  void setOpusDecodeCallBack(OpusDecodeCallBack callBack){
    opusDecodeCallBack=callBack;
  }

  void setPhoneCallStatusChange(OnPhoneCallStatusChange callBack){
    phoneCallStatusChange=callBack;
  }


  void setJlDeviceCommandDecodeCallBack(JlDeviceCommandDecodeCallBack callBack){
    jlDeviceCommandDecodeCallBack=callBack;
  }

  void removeOpusDecodeCallBack(){
    opusDecodeCallBack=null;
  }

  void removeJlDeviceCommandDecodeCallBack(){
    jlDeviceCommandDecodeCallBack=null;
  }

  void removePhoneCallBack(){
    phoneCallStatusChange=null;
  }

  /// 添加蓝牙扫描监听
  void addScanListener(BlueDeviceCallback callback) {
    _scanListeners.add(callback);
  }

  /// 添加 BT 事件监听
  void addBtCallback(BtRcspCallBack callback) {
    _btListeners.add(callback);
  }

  /// 移除扫描监听
  void removeScanListener(BlueDeviceCallback callback) {
    _scanListeners.remove(callback);
  }

  /// 移除 BT 事件监听
  void removeBtCallback(BtRcspCallBack callback) {
    _btListeners.remove(callback);
  }

  /// 添加 Eqchange 事件监听
  void addEqChangeCallback(JlEqChangeCallBack callback) {
    _eqSettingChange.add(callback);
  }

  /// 移除扫描监听
  void removeEqChangeListener(JlEqChangeCallBack callback) {
    _eqSettingChange.remove(callback);
  }


  /// 添加 指令 事件监听
  void addCommandCmdCallback(JlDeviceCommandCallBack callback) {
    commandCmdCallBack.add(callback);
  }

  /// 移除 指令 事件监听
  void removeCommandCmdCallback(JlDeviceCommandCallBack callback) {
    commandCmdCallBack.remove(callback);
  }

  /// 初始化SDK
  Future<bool?> initSdk(Map<String,dynamic> paramMap) async{
    return JlPluginPlatform.instance.initSdk(paramMap);
  }

  /// 开始搜索蓝牙
  Future<bool?> startScanBlue() async{
    return JlPluginPlatform.instance.startScanBlue();
  }

  /// 停止搜索蓝牙
  Future<bool?> stopScanBlue() async{
    return JlPluginPlatform.instance.stopScanBlue();
  }

  /// 蓝牙连接
  Future<JlResult> connectBlue(BlueDevice device) async{
    var resultMap=await JlPluginPlatform.instance.connectBlue(device.address,device.connectWay);
    var result= JlResult.fromJson(Map.from(resultMap ?? {}));
    return result;
  }
  /// 蓝牙连接
  Future<JlResult> connectBlue2(String address,int connectWay) async{
    var resultMap=await JlPluginPlatform.instance.connectBlue(address,connectWay);
    var result= JlResult.fromJson(Map.from(resultMap ?? {}));
    return result;
  }

  /// 取消连接
  Future<bool?> disconnectBlue(BlueDevice device) async{
    return JlPluginPlatform.instance.disconnectBlue(device);
  }

  /// 取消连接
  Future<bool?> disconnectBlue2(String address) async{
    return JlPluginPlatform.instance.disconnectBlue2(address);
  }

  /// 按键设置
  Future<JlResult> configKeySettings(List<KeySetting> keySettingList) async{
    return JlPluginPlatform.instance.configKeySettings(keySettingList);
  }

  /// 设备设置信息 int mask = 0x01; //属性掩码， 不能为0 mask = 0xffffffff; //获取所有属性
  void deviceSettingInfo(int mask,{required JlOnDevicesSuccessCallBack successCall,required JlOnErrorCallBack onErrorCall}) async{
   var resultMap=await JlPluginPlatform.instance.getDevicesSetting( mask);
   if(resultMap["code"]==1){
     //成功
     var advInfoBean=ADVInfoResponse.fromJson(jsonDecode(resultMap["advInfo"]));
     successCall(advInfoBean);
   }else{
     var jlResult=JlResult.fromJson(Map.from(resultMap));
     onErrorCall(jlResult);
   }
  }

  //获取EQ设置
  void getEqSetting() async{
    var resultMap=await JlPluginPlatform.instance.getEqSetting();
  }

  //设置EQ
  Future<bool?> setEqSetting(EqInfo eqInfo) async{
    return await JlPluginPlatform.instance.settingEq(eqInfo);
  }

  //发送指令
  Future sendCmd(String sendCmd) async{
    return await JlPluginPlatform.instance.sendCmd(sendCmd);
  }

  //设置耳机功能
  Future<Map?> modifyHeadsetFunctions(int attrType, List<Int> paramData) async{
    return await JlPluginPlatform.instance.modifyHeadsetFunctions(attrType, paramData) ;
  }

  //修改耳机设备名字
  Future<JlResult> changeDeviceName(String name) async{
    var resultMap= await JlPluginPlatform.instance.changeDeviceName(name);
    var result= JlResult.fromJson(Map.from(resultMap ?? {}));
    return result;
  }

  Future<JlResult> rebootDevice() async{
    var resultMap= await JlPluginPlatform.instance.rebootDevice();
    var result= JlResult.fromJson(Map.from(resultMap ?? {}));
    return result;
  }

  //获取当前设备
  Future<BlueDevice?> getCurrentDevices() async{
    var callResult=await JlPluginPlatform.instance.getCurrentDevices();
    var result=callResult!["result"] as bool;
    if(result){
      final device = BlueDevice.fromMap(callResult["device"]);
      return device;
    }else{
      return null;
    }
  }

  //获取历史设备
  Future<List<HistoryBluetoothDevice>?> getHistoryBluetoothDeviceList() async{
    var result= await JlPluginPlatform.instance.getHistoryBluetoothDeviceList();
    var blueList=(result as List).map((item)=>HistoryBluetoothDevice.fromJson(Map.from(item))).toList();
    return blueList;
  }

  @override
  Future<HistoryBluetoothDevice?> findHistoryBluetoothDevice(String address) async{
    var result= await JlPluginPlatform.instance.findHistoryBluetoothDevice(address);

    if(result!["result"]==false){
      return null;
    }else{
      Map<String, dynamic> deviceInfo = Map<String, dynamic>.from(result!["device"]);
      var jlResult=HistoryBluetoothDevice.fromJson(deviceInfo);
      return jlResult;
    }
  }

  Future<bool> isConnecting() async{
    return await JlPluginPlatform.instance.isConnecting() ??false;
  }

  Future<bool?> isConnectioned() async{
    return await JlPluginPlatform.instance.isConnectioned() ??false;
  }

  Future<bool?> isScanning() async{
    return await JlPluginPlatform.instance.isScanning() ??false;
  }

  Future<bool?> isInit() async{
    return await JlPluginPlatform.instance.isInit() ??false;
  }

  Future<bool> removeHistoryBluetoothDevice(String address) async{
    return await JlPluginPlatform.instance.removeHistoryBluetoothDevice(address) ??false;
  }

  Future<bool> stopReconnect() async{
    return await JlPluginPlatform.instance.stopReconnect() ??false;
  }

  Future<bool> startReconnect() async{
    return await JlPluginPlatform.instance.startReconnect() ??false;
  }

  @override
  Future<bool?> startRecord() async{
    return await JlPluginPlatform.instance.startRecord() ??false;
  }

  @override
  Future<bool?> stopRecord() async{
    return await JlPluginPlatform.instance.stopRecord() ??false;
  }

  // @override
  // Future<bool> getRecordStatus() async{
  //   return await JlPluginPlatform.instance.getRecordStatus() ??false;
  // }

  Future<bool> startDecode() async{
    return await JlPluginPlatform.instance.startDecode() ??false;
  }

  Future<bool> stopDecode() async{
    return await JlPluginPlatform.instance.stopDecode() ??false;
  }

  Future<bool> releaseDecode() async{
    return await JlPluginPlatform.instance.releaseDecode() ??false;
  }

  Future decodeOpus(Uint8List data) async{
     await JlPluginPlatform.instance.decodeOpus(data);
  }
}
